/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ve.terminal.db;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import ve.terminal.controlador.Sesion;
import ve.terminal.excepciones.BaseDeDatosExcepcion;

/**
 *
 * @author Jesus Graterol
 * 
 * La idea de esta clase es ahorrarnos el trabajo de construir las consultas
 * con la base de datos cada vez que queramos hacer una, basta con construir una
 * instancia de este objeto pasandole una tabla de hash que contiene para cada 
 * entrada el nombre de la columna en base de datos y el 
 * 
 */
public class TraductorSentencias {
    

    /**
     * Obtiene el codigo sql de un insert en la base de datos
     * @param entidad TNombre de la tabla
     * @param campos <nombre del campo, valor del campo>
     * @return El query
     */
    public static String getInsert(String entidad, HashMap<String, Object> campos){
        String query = "";
        String values = "";
        query+="INSERT INTO "+Sesion.getDbEsquema()+"."+entidad+" (";
        //recorriendo los nombres de los campos
        Iterator<String> iteraCampos = campos.keySet().iterator();
        while (iteraCampos.hasNext()) {
            String campo = iteraCampos.next();
            Object valor = campos.get(campo);
            if(valor instanceof String || valor instanceof Character){
                values+="'"+valor+"'";
            } else {
                values+=valor;
            }
            query+=campo;
            if(iteraCampos.hasNext()){
                values+=",";
                query+=",";
            }
        }
        query+=") VALUES ("+values+")";
        
        return query;
    }
    
    /**
     * Obtiene el codigo sql de un delete en base de datos
     * @param entidad
     * @param where - <nombre del campo, valor> de las condiciones del where
     * @return El query
     */
    public static String getDelete(String entidad, HashMap<String, Object> where){
        String query = "";
        String whereTxt = "";
        query+="delete from "+Sesion.getDbEsquema()+"."+entidad+" ";
        //recorriendo los nombres de los campos
        for(Iterator<String> iteraCampos = where.keySet().iterator(); where.keySet().iterator().hasNext();) {
            String campo = iteraCampos.next();
            Object valor = where.get(campo);
            if(valor instanceof String || valor instanceof Character){
                whereTxt+=campo+"= '"+valor+"' ";
            } else {
                whereTxt+=campo+"="+valor+" ";
            }
            if(iteraCampos.hasNext()){
                whereTxt+=" and ";
            }
        }
        if (!whereTxt.equalsIgnoreCase(""))
            query+=" where "+whereTxt;
        
        return query;
    }
    
    /**
     * Obtiene el codigo sql de un delete en base de datos
     * @param entidad
     * @param where - <nombre del campo, valor> de las condiciones del where
     * @return El query
     */
    public static String getUpdate(
            String entidad, 
            HashMap<String, Object> set, 
            HashMap<String, Object> where){
        
        String query = "";
        String whereTxt = "";
        String setTxt="";
        query+="update "+Sesion.getDbEsquema()+"."+entidad+" set ";
        //recorriendo los nombres de los campos para el set
        for(Iterator<String> iteraSet = set.keySet().iterator(); set.keySet().iterator().hasNext();) {
            String campo = iteraSet.next();
            Object valor = set.get(campo);
            if(valor instanceof String || valor instanceof Character){
                setTxt+=campo+"= '"+valor+"' ";
            } else {
                setTxt+=campo+"="+valor+" ";
            }
            if(iteraSet.hasNext()){
                setTxt+=", ";
            }
        }
        query+=setTxt+" ";
        //recorriendo los nombres de los campos para el where
        for(Iterator<String> iteraCampos = where.keySet().iterator(); where.keySet().iterator().hasNext();) {
            String campo = iteraCampos.next();
            Object valor = where.get(campo);
            if(valor instanceof String || valor instanceof Character){
                whereTxt+=campo+"= '"+valor+"' ";
            } else {
                whereTxt+=campo+"="+valor+" ";
            }
            if(iteraCampos.hasNext()){
                whereTxt+=" and ";
            }
        }
        if(!whereTxt.equalsIgnoreCase(""))
            query+=" where "+whereTxt;
        
        return query;
    }
    
    /**
     * Genera el código sql correspondiente a una sentencia de select
     * con groupby y order by. Si alguno de los parametros de tipo HashMap es 
     * vacío se asume que se quieren usar todos los campos.
     * @param select
     * @param from
     * @param where
     * @param groupby
     * @param orderby
     * @return EL query
     */
    public static String getSelectFull(
            Vector<String> select,
            String from,
            HashMap<String, Object> where,
            Vector<String> groupby,
            Vector<String> orderby
            ){
        String query = "";
        String whereTxt = "";
        String selectTxt = "";
        String groupbyTxt = "";
        String orderbyTxt = "";
        query+="select ";
        //recorriendo campos para el select
        for(int i=0; i<select.size();i++) {
            String campo = select.elementAt(i);
            selectTxt+=campo+" ";
            
            if(i!=(select.size()-1)){
                selectTxt+=" , ";
            }
        }
         if(selectTxt.equalsIgnoreCase("")){
             query+=" * ";
         } else {
             query+=selectTxt+" ";
         }
         
        //concatenando el from
        query+=" from "+Sesion.getDbEsquema()+"."+from+" ";
        
        //recorriendo los nombres de los campos para el where
        for(Iterator<String> iteraCampos = where.keySet().iterator(); where.keySet().iterator().hasNext();) {
            String campo = iteraCampos.next();
            Object valor = where.get(campo);
            if(valor instanceof String || valor instanceof Character){
                whereTxt+=campo+"= '"+valor+"' ";
            } else {
                whereTxt+=campo+"="+valor+" ";
            }
            if(iteraCampos.hasNext()){
                whereTxt+=" and ";
            }
        }
        if(!whereTxt.equalsIgnoreCase("")){
            query+=" where "+whereTxt+" ";
        }
        
        //concatenando el groupby
        for(int i=0; i<groupby.size();i++) {
            String campo = groupby.elementAt(i);
            groupbyTxt+=campo+" ";
            
            if(i!=(select.size()-1)){
                groupbyTxt+=" , ";
            }
        }
         if(!groupbyTxt.equalsIgnoreCase("")){
             query+=" group by "+groupbyTxt+" ";
         } 
         
        //concatenando el orderby
        for(int i=0; i<orderby.size();i++) {
           String campo = orderby.elementAt(i);
           orderbyTxt+=campo+" ";
           
           if(i!=(select.size()-1)){
               orderbyTxt+=" , ";
           }
        }
        if(!orderbyTxt.equalsIgnoreCase("")){
            query+=" group by "+orderbyTxt+" ";
        } 
        return query;
    }
    
    /**
     * Genera el código sql de una consulta select con los datos basicos. 
     * Si alguno de los parametros de tipo HashMap es 
     * vacío se asume que se quieren usar todos los campos.
     * @param select
     * @param from
     * @param where
     * @return El query
     */
    public static String getSelect(
            Vector<String> select,
            String from,
            HashMap<String, Object> where
            ){
        return TraductorSentencias.getSelectFull(select, from, where, new Vector(), new Vector());
    }
    
    
    /**
     * Traduce el resultado obtenido de la base de datos a objeto java
     * @param rs
     * @return Vector con los datos del objeto
     * @throws BaseDeDatosExcepcion 
     */
    public static Vector traducirResultado(ResultSet rs, int[] tipos) throws BaseDeDatosExcepcion{
        Vector resultado = new Vector();
        try {
            int i=0;
            while(rs.next()){
                switch (tipos[i]){
                    case Sesion.TIPO_DATO_INT:
                        resultado.addElement(new Integer(rs.getInt(i)));
                        break;
                    case Sesion.TIPO_DATO_STRING:
                        resultado.addElement(rs.getString(i));
                        break;
                    case Sesion.TIPO_DATO_FLOAT:
                        resultado.addElement(rs.getFloat(i));
                        break;
                    case Sesion.TIPO_DATO_DOUBLE:
                        resultado.addElement(rs.getDouble(i));
                        break;
                    case Sesion.TIPO_DATO_BOOLEAN:
                        resultado.addElement(rs.getBoolean(i));
                        break;
                    case Sesion.TIPO_DATO_LONG:
                        resultado.addElement(new Long(rs.getLong(i)));
                        break;
                    case Sesion.TIPO_DATO_DATE:
                        resultado.addElement (rs.getDate(i));
                        break;
                }
                i++;
            }
        } catch (SQLException ex) {
            Logger.getLogger(TraductorSentencias.class.getName()).log(Level.SEVERE, null, ex);
            throw new BaseDeDatosExcepcion("Error obteniendo entidad de la base de datos");
        }
        
        return resultado;
    }
}
